package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.JobTypeEnum;
import com.ruoyi.common.enums.YnStatusEnum;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.AppCreateJobBill;
import com.ruoyi.system.domain.JobPersonnelBuilder;
import com.ruoyi.system.domain.JobPlanBillDeclare;
import com.ruoyi.system.entity.AppJobSignedConfig;
import com.ruoyi.system.mapper.AppJobSignedConfigMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.AppCreateJobBillService;
import com.ruoyi.system.service.AppJobSignedConfigService;
import com.ruoyi.system.service.JobPlanBillDeclareService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (AppJobSignedConfig)表服务实现类
 *
 * @author makejava
 * @since 2023-06-25 13:51:48
 */
@Slf4j
@Service("appJobSignedConfigService")
public class AppJobSignedConfigServiceImpl implements AppJobSignedConfigService {

    @Value("#{${app.job.signed.admin}}")
    private Map<Integer, String> appJobSignedAdmin;

    @Resource
    private RedisCache redisCache;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private AppJobSignedConfigMapper appJobSignedConfigDao;
    @Autowired
    private AppCreateJobBillService appCreateJobBillService;
    @Autowired
    private JobPlanBillDeclareService jobPlanBillDeclareService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public AppJobSignedConfig queryById(Integer id) {
        return this.appJobSignedConfigDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param appJobSignedConfig 筛选条件
     * @param pageRequest        分页对象
     * @return 查询结果
     */
    @Override
    public Page<AppJobSignedConfig> queryByPage(AppJobSignedConfig appJobSignedConfig, PageRequest pageRequest) {
        long total = this.appJobSignedConfigDao.count(appJobSignedConfig);
        return new PageImpl<>(this.appJobSignedConfigDao.queryAllByLimit(appJobSignedConfig, pageRequest), pageRequest, total);
    }

    @Override
    public List<AppJobSignedConfig> queryNodeConfig(AppJobSignedConfig appJobSignedConfig) {
        List<AppJobSignedConfig> appJobSignedConfigListResp = new ArrayList<>();

        AppCreateJobBill appCreateJobBill = appCreateJobBillService.queryById(appJobSignedConfig.getCreateJobId());
        if (null == appCreateJobBill) {
            log.error("未查询到作业票...");
            return appJobSignedConfigListResp;
        }

        JobPlanBillDeclare jobPlanBillDeclare = new JobPlanBillDeclare();
        jobPlanBillDeclare.setBillNumber(appCreateJobBill.getPtw());
        List<JobPlanBillDeclare> jobPlanBillDeclares = jobPlanBillDeclareService.queryAll(jobPlanBillDeclare);
        if (CollectionUtils.isEmpty(jobPlanBillDeclares)) {
            log.error("未查询到作业票 申报为空...");
            return appJobSignedConfigListResp;
        }

        JobPlanBillDeclare planBillDeclare = jobPlanBillDeclares.stream().findFirst().orElse(new JobPlanBillDeclare());
        if (StringUtils.isEmpty(planBillDeclare.getJobPersonnel())) {
            log.error("作业人员为空 申报为空...");
            return appJobSignedConfigListResp;
        }

        List<JobPersonnelBuilder> jobPersonnelBuilders = JSON.parseArray(planBillDeclare.getJobPersonnel(), JobPersonnelBuilder.class);
        for (JobPersonnelBuilder var : jobPersonnelBuilders) {
            if ("out".equals(var.getType())) {
                SysUser vidInfo = sysUserMapper.getVidInfo(Long.valueOf(var.getId()));
                var.setId(vidInfo.getUserId().intValue());
                var.setName(vidInfo.getNickName());
            }
        }

        if (appJobSignedConfig.getPersonnelType().equals("out")) {
            SysUser vidInfo = sysUserMapper.getVidInfo(Long.valueOf(planBillDeclare.getJobPersonChargeId()));
            planBillDeclare.setJobPersonChargeId(vidInfo.getUserId().toString());
            planBillDeclare.setJobPersonCharge(vidInfo.getNickName());
        }

        appJobSignedConfig.setYn(YnStatusEnum.Y.getCode());
        List<AppJobSignedConfig> appJobSignedConfigList = appJobSignedConfigDao.queryAll(appJobSignedConfig);
        if (CollectionUtils.isEmpty(appJobSignedConfigList)) {
            return appJobSignedConfigListResp;
        }

        Map<String, List<AppJobSignedConfig>> listMap = appJobSignedConfigList.stream()
                .collect(Collectors.groupingBy(AppJobSignedConfig::getNodeName));

        listMap.forEach((k, v) -> {
            AppJobSignedConfig appJobSignedConfigResp = new AppJobSignedConfig();
            appJobSignedConfigResp.setNodeName(k);

            List<AppJobSignedConfig.NodeConfigName> configNameList = new ArrayList<>();
            for (AppJobSignedConfig var : v) {
                AppJobSignedConfig.NodeConfigName nodeConfigName = new AppJobSignedConfig.NodeConfigName();
                nodeConfigName.setSignedBy(var.getSignedBy());
                nodeConfigName.setSignedName(var.getSignedName());
                configNameList.add(nodeConfigName);
            }

            appJobSignedConfigResp.setConfigNameList(configNameList);
            appJobSignedConfigListResp.add(appJobSignedConfigResp);
        });

        /** 动土 **/
        if ("4".equals(appJobSignedConfig.getJobType())) {
            // zyfwq-作业范围签字人 = 作业负责人
            AppJobSignedConfig buildJobSignedHead = buildJobSignedHead("zyfwqz", planBillDeclare);
            appJobSignedConfigListResp.add(buildJobSignedHead);
        }

        /** 5-临时用电 **/
        if (!"5".equals(appJobSignedConfig.getJobType())) {
            // 接收交底签字人 = 所有作业人员
            appJobSignedConfigListResp.add(buildJobSigned("jsjdr", jobPersonnelBuilders));

            // yjqm1 = 作业负责人签字
            AppJobSignedConfig appJobSignedConfigBase = buildJobSignedHead("yjqm1", planBillDeclare);
            appJobSignedConfigListResp.add(appJobSignedConfigBase);
        }

        /** 5-临时用电 **/
        if ("5".equals(appJobSignedConfig.getJobType())) {
            // yjqm2-签字人 = 作业负责人
            AppJobSignedConfig buildJobSignedHead = buildJobSignedHead("yjqm2", planBillDeclare);
            appJobSignedConfigListResp.add(buildJobSignedHead);
        }

        /** 盲板抽堵安全作业 **/
        if (appJobSignedConfig.getJobType().equals(JobTypeEnum.BLIND_PLATE_SECURITY_JOB_BILL.getCode().toString())) {
            // yjqm3 = 所有作业人员
            appJobSignedConfigListResp.add(buildJobSigned("yjqm3", jobPersonnelBuilders));
        }

        Map<String, Object> mapBuild = redisCache.getCacheMap("job_bill_q_m_config");
        if (!MapUtils.isEmpty(mapBuild)) {
            mapBuild.forEach((k, v) -> {
                if (appJobSignedConfig.getJobType().equals(k)) {
                    List<String> list = JSON.parseArray(v.toString(), String.class);
                    for (String var : list) {
                        // 相关环节的签字人 = 所有作业人员
                        appJobSignedConfigListResp.add(buildJobSigned(var, jobPersonnelBuilders));
                    }
                }
            });
        }

        /** 动火安全作业 **/
        if ("2".equals(appJobSignedConfig.getJobType()) && "二级（72H）".equals(appJobSignedConfig.getJobGrade())) {
            Map<String, Object> mapBuildCase = redisCache.getCacheMap("job_bill_q_m_config_case");
            if (!MapUtils.isEmpty(mapBuildCase)) {
                mapBuildCase.forEach((k, v) -> {
                    if (appJobSignedConfig.getJobType().equals(k)) {
                        List<String> list = JSON.parseArray(v.toString(), String.class);
                        for (String var : list) {
                            // 相关环节的签字人 = 作业人员
                            appJobSignedConfigListResp.add(buildJobSigned(var, jobPersonnelBuilders));
                        }
                    }
                });
            }
        }

        buildSignedHeads(appJobSignedConfigListResp);
        return appJobSignedConfigListResp;
    }

    /**
     * 所有签字环节追加授权签字人
     * 将运行管理员，追加到所有签字环节中
     *
     * @param appJobSignedConfigListResp
     */
    private void buildSignedHeads(List<AppJobSignedConfig> appJobSignedConfigListResp) {
        for (AppJobSignedConfig var : appJobSignedConfigListResp) {
            List<AppJobSignedConfig.NodeConfigName> configNameList = var.getConfigNameList();
            if (!MapUtils.isEmpty(appJobSignedAdmin)) {
                appJobSignedAdmin.forEach((ks, vs) -> {
                    AppJobSignedConfig.NodeConfigName nodeConfigNameCaseBlock = new AppJobSignedConfig.NodeConfigName();
                    nodeConfigNameCaseBlock.setSignedBy(ks);
                    nodeConfigNameCaseBlock.setSignedName(vs);
                    configNameList.add(nodeConfigNameCaseBlock);
                });
            }
        }
    }

    public AppJobSignedConfig buildJobSignedHead(String key, JobPlanBillDeclare planBillDeclare) {
        AppJobSignedConfig appJobSignedConfigBase = new AppJobSignedConfig();
        appJobSignedConfigBase.setNodeName(key);

        List<AppJobSignedConfig.NodeConfigName> configNameListBase = new ArrayList<>();
        AppJobSignedConfig.NodeConfigName nodeConfigNameBase = new AppJobSignedConfig.NodeConfigName();
        // 作业负责人
        nodeConfigNameBase.setSignedBy(Integer.valueOf(planBillDeclare.getJobPersonChargeId()));
        nodeConfigNameBase.setSignedName(planBillDeclare.getJobPersonCharge());
        configNameListBase.add(nodeConfigNameBase);
        appJobSignedConfigBase.setConfigNameList(configNameListBase);

        return appJobSignedConfigBase;
    }

    /**
     * key 绑定签名人
     * @param key   待签名的字段, 比如；yjqm1、aqjdr等等
     * @param jobPersonnelBuilders  作业人
     * @return
     */
    public AppJobSignedConfig buildJobSigned(String key, List<JobPersonnelBuilder> jobPersonnelBuilders) {
        AppJobSignedConfig appJobSignedConfig = new AppJobSignedConfig();
        appJobSignedConfig.setNodeName(key);
        List<AppJobSignedConfig.NodeConfigName> configNameListCaseBlock = new ArrayList<>();

        for (JobPersonnelBuilder var : jobPersonnelBuilders) {
            AppJobSignedConfig.NodeConfigName nodeConfigNameCaseBlock = new AppJobSignedConfig.NodeConfigName();
            nodeConfigNameCaseBlock.setSignedBy(var.getId());
            nodeConfigNameCaseBlock.setSignedName(var.getName());
            configNameListCaseBlock.add(nodeConfigNameCaseBlock);
        }

        appJobSignedConfig.setConfigNameList(configNameListCaseBlock);
        return appJobSignedConfig;
    }

    @Override
    public List<AppJobSignedConfig> queryAll(AppJobSignedConfig appJobSignedConfig) {
        List<AppJobSignedConfig> respAppJobSignedConfig = new ArrayList<>();
        appJobSignedConfig.setYn(YnStatusEnum.Y.getCode());
        List<AppJobSignedConfig> jobSignedConfigList = appJobSignedConfigDao.queryAll(appJobSignedConfig);

        Map<String, List<AppJobSignedConfig>> collect = jobSignedConfigList.stream()
                .collect(Collectors.groupingBy(a -> a.getJobType() + "-" + a.getJobGrade() + "-" + a.getNodeName() + "-" + a.getNodeNameValue()));

        collect.forEach((k, v) -> {
            String[] split = k.split("-");
            AppJobSignedConfig appJobSignedConfigResp = new AppJobSignedConfig();
            appJobSignedConfigResp.setJobType(split[0]);
            appJobSignedConfigResp.setJobGrade(split[1]);
            appJobSignedConfigResp.setNodeName(split[2]);
            appJobSignedConfigResp.setNodeNameValue(split[3]);

            List<AppJobSignedConfig.NodeConfigName> nodeConfigNames = new ArrayList<>();

            for (AppJobSignedConfig var : v) {
                AppJobSignedConfig.NodeConfigName nodeConfigNameCase = new AppJobSignedConfig.NodeConfigName();
                nodeConfigNameCase.setSignedBy(var.getSignedBy());
                nodeConfigNameCase.setSignedName(var.getSignedName());
                nodeConfigNames.add(nodeConfigNameCase);
            }

            appJobSignedConfigResp.setConfigNameList(nodeConfigNames);

            respAppJobSignedConfig.add(appJobSignedConfigResp);
        });

        return respAppJobSignedConfig;
    }

    /**
     * 新增数据
     *
     * @param appJobSignedConfig 实例对象
     * @return 实例对象
     */
    @Override
    public AppJobSignedConfig insert(AppJobSignedConfig appJobSignedConfig) {
        this.appJobSignedConfigDao.insert(appJobSignedConfig);
        return appJobSignedConfig;
    }

    /**
     * 修改数据
     *
     * @param appJobSignedConfig 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppJobSignedConfig update(AppJobSignedConfig appJobSignedConfig) {
        AppJobSignedConfig appJobSignedConfigParam = new AppJobSignedConfig();
        appJobSignedConfigParam.setJobType(appJobSignedConfig.getJobType());

        if (StringUtils.isNotBlank(appJobSignedConfig.getJobGrade()) && !"null".equals(appJobSignedConfig.getJobGrade())) {
            appJobSignedConfigParam.setJobGrade(appJobSignedConfig.getJobGrade());
        }

        appJobSignedConfigParam.setNodeName(appJobSignedConfig.getNodeName());
        List<AppJobSignedConfig> appJobSignedConfigList = appJobSignedConfigDao.queryAll(appJobSignedConfigParam);
        List<Integer> ids = appJobSignedConfigList.stream().map(AppJobSignedConfig::getId).collect(Collectors.toList());

        appJobSignedConfigDao.updateBatch(ids);

        List<AppJobSignedConfig> save = new ArrayList<>();
        for (AppJobSignedConfig.NodeConfigName var : appJobSignedConfig.getConfigNameList()) {
            AppJobSignedConfig saveAppJobSignedConfig = new AppJobSignedConfig();
            BeanUtils.copyProperties(appJobSignedConfig, saveAppJobSignedConfig);
            saveAppJobSignedConfig.setSignedBy(var.getSignedBy());
            saveAppJobSignedConfig.setSignedName(var.getSignedName());
            saveAppJobSignedConfig.setYn(YnStatusEnum.Y.getCode());
            saveAppJobSignedConfig.setCreatedDate(new Date());
            save.add(saveAppJobSignedConfig);
        }

        appJobSignedConfigDao.insertBatch(save);

        return this.queryById(appJobSignedConfig.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.appJobSignedConfigDao.deleteById(id) > 0;
    }
}
